﻿using System.Windows.Forms;
using BasecampRestAPI;
using NUnit.Framework;
using SplitToDoList;
using TestBasecampRestAPI.Fakes;
using TestBasecampRestAPI.TestBasecampUI;
using TestBasecampRestAPI.TestMoveToDoList;

namespace TestBasecampRestAPI.TestSplitToDoList
{
	[TestFixture]
	public class TestMainFormMediator
	{
		FakeCredentialsForm _credentials;
		FakeMainForm _form;
		MainFormMediator _mediator;
		FakeBaseCamp _camp;
		private FakeRestWebService _service;

		[SetUp]
		public void Setup()
		{
			_credentials = FakeCredentialsForm.GetInstance();
			_service = FakeRestWebService.GetInstance();
			_credentials.ServiceGetFakeResult = _service;
			_form = FakeMainForm.GetInstance();
			_form.CredentialsFormGetFakeResult = _credentials;
			_camp = FakeBaseCamp.GetInstance();
			_form.GetBaseCampFromCredentialsFakeCampResult = _camp;
			_form.GetBaseCampFromCredentialsFakeResult = true;
			_mediator = MainFormMediator.GetInstance(_form);
		}


		[Test]
		public void Construct()
		{
			Assert.IsNotNull(_mediator);
		}

		[Test]
		public void LoadCancelCredentials()
		{
			_form.GetBaseCampFromCredentialsFakeResult = false;
			_form.GetBaseCampFromCredentialsFakeCampResult = null;
			_mediator.Load();
			Assert.IsTrue(_form.GetBaseCampFromCredentialsCalled);
			Assert.IsFalse(_camp.ProjectsGetCalled);
		}

		[Test]
		public void LoadAcceptCredentialsNoProjectsSplitButtonDisabled()
		{
			_camp.ProjectsGetFakeResult = new IProject[0];
			_form.GetBaseCampFakeResult = _camp;
			AcceptCredentials();
			_mediator.Load();
			Assert.IsTrue(_form.GetBaseCampFromCredentialsCalled);
			Assert.IsTrue(_camp.ProjectsGetCalled);
			Assert.IsFalse(_form.CloseCalled);
			Assert.IsFalse(_form.AddProjectCalled);
			Assert.IsTrue(_form.SplitButtonEnabledSetCalled);
			Assert.IsFalse(_form.SplitButtonEnabledSetLastValue);
		}

		private void AcceptCredentials()
		{
			_form.GetBaseCampFromCredentialsFakeCampResult = _camp;
			_form.GetBaseCampFromCredentialsFakeResult = true;
		}

		[Test]
		public void LoadAcceptCredentialsWithProjects()
		{
			_camp.ProjectsGetFakeResult = new IProject[]
			{
				new FakeProject { Name = "Foo", Id = 24 },
				new FakeProject { Name = "Bar", Id = 23 }
			};
			_form.GetBaseCampFakeResult = _camp;
			AcceptCredentials();
			_mediator.Load();
			Assert.IsTrue(_form.AddProjectCalled);
			Assert.IsTrue(_form.AddProjectCalledFor("Bar"));
			Assert.IsTrue(_form.AddProjectCalledFor("Foo"));
			Assert.Less(_form.AddProjectIndexFor("Bar"), _form.AddProjectIndexFor("Foo"));
			Assert.IsTrue(_form.ProjectSelectedIndexSetCalled);
			Assert.AreEqual(0, _form.ProjectSelectedIndexSetLastValue);
		}

		[Test]
		public void SourceProjectSelectedIndexChangedNoToDoLists()
		{
			FakeProject barProject = new FakeProject { Name = "Bar", Id = 23 };
			barProject.ToDoListsGetFakeResult = new IToDoList[0];
			_camp.ProjectsGetFakeResult = new IProject[]
			{
				new FakeProject { Name = "Foo", Id = 24 },
				barProject
			};
			_form.GetBaseCampFakeResult = _camp;
			_form.ProjectSelectedIndexGetFakeResult = 0;
			AcceptCredentials();
			_mediator.Load();
			_mediator.SourceProjectSelectedIndexChanged();
			Assert.IsTrue(_form.ProjectSelectedIndexGetCalled);
			Assert.IsTrue(barProject.ToDoListsGetCalled);
			Assert.IsTrue(_form.ClearToDoListsCalled);
			Assert.IsFalse(_form.ToDoListsAddItemCalled);
		}

		[Test]
		public void SourceToDoListSelectedIndexChangedNoListItems()
		{
			FakeProject barProject = new FakeProject { Name = "Bar", Id = 23 };
			FakeToDoList list = new FakeToDoList
			{
				Id = 4343,
				Name = "Stuff to do",
				Items = new IToDoListItem[0]
			};
			barProject.ToDoListsGetFakeResult = new IToDoList[] { list };
			_camp.ProjectsGetFakeResult = new IProject[]
			{
				new FakeProject { Name = "Foo", Id = 24 },
				barProject
			};
			_form.GetBaseCampFakeResult = _camp;
			_form.ProjectSelectedIndexGetFakeResult = 0;
			_form.ToDoListSelectedIndexGetFakeResult = 0;
			AcceptCredentials();
			_mediator.Load();
			_mediator.SourceProjectSelectedIndexChanged();
			_mediator.SourceToDoListSelectedIndexChanged();
			Assert.IsTrue(_form.ClearToDoListItemsCalled);
		}

		[Test]
		public void SourceToDoListSelectedIndexChangedWithListItems()
		{
			FakeProject barProject = new FakeProject { Name = "Bar", Id = 23 };
			const string itemContent = "This is item one";
			FakeToDoListItem item = new FakeToDoListItem
			{
				Id = 4444,
				Content = itemContent
			};
			FakeToDoList list = new FakeToDoList
			{
				Id = 4343,
				Name = "Stuff to do",
				Items = new IToDoListItem[] { item }
			};
			barProject.ToDoListsGetFakeResult = new IToDoList[] { list };
			_camp.ProjectsGetFakeResult = new IProject[]
			{
				new FakeProject { Name = "Foo", Id = 24 },
				barProject
			};
			_form.GetBaseCampFakeResult = _camp;
			_form.ProjectSelectedIndexGetFakeResult = 0;
			_form.ToDoListSelectedIndexGetFakeResult = 0;
			AcceptCredentials();
			_mediator.Load();
			_mediator.SourceProjectSelectedIndexChanged();
			_mediator.SourceToDoListSelectedIndexChanged();
			Assert.IsTrue(_form.ClearToDoListItemsCalled);
			Assert.IsTrue(_form.ToDoListItemsAddItemCalled);
			Assert.AreEqual(itemContent, _form.ToDoListItemsAddItemLastItem);
		}

		[Test]
		public void NonEmptyListNameEnablesSplitButton()
		{
			_form.NewListNameGetFakeResult = "New list";
			_mediator.NewListNameChanged();
			Assert.IsTrue(_form.SplitButtonEnabledSetCalled);
			Assert.IsTrue(_form.SplitButtonEnabledSetLastValue);
		}

		[Test]
		public void SplitListCreatesNewListWithSelectedItems()
		{
			FakeProject barProject = new FakeProject { Name = "Bar", Id = 23 };
			const string itemContent = "This is item one";
			FakeToDoListItem item = new FakeToDoListItem
			{
				Id = 4444,
				Content = itemContent
			};
			FakeToDoList list = new FakeToDoList
			{
				Id = 4343,
				Name = "Stuff to do",
				Items = new IToDoListItem[] { item }
			};
			barProject.ToDoListsGetFakeResult = new IToDoList[] { list };
			FakeProject fooProject = new FakeProject { Name = "Foo", Id = 24 };
			fooProject.ToDoListsGetFakeResult = new IToDoList[0];
			_camp.ProjectsGetFakeResult = new IProject[]
			{
				fooProject,
				barProject
			};
			_form.GetBaseCampFakeResult = _camp;
			_form.ProjectSelectedIndexGetFakeResult = 0;
			_form.ToDoListSelectedIndexGetFakeResult = 0;
			const string newListName = "New list";
			FakeToDoListItem newItem = new FakeToDoListItem
			{
				Id = 6848,
				Content = itemContent
			};
			FakeToDoList newList = new FakeToDoList
			{
				Id = 8873,
				Name = newListName,
				Items = new IToDoListItem[0]
			};
			newList.CreateItemFakeResult = newItem;
			barProject.CreateToDoListFakeResult = newList;
			_form.NewListNameGetFakeResult = newListName;
			_form.SelectedListItemsGetFakeResult = new[] { 0 };
			AcceptCredentials();
			_mediator.Load();
			_mediator.SourceProjectSelectedIndexChanged();
			_mediator.SourceToDoListSelectedIndexChanged();
			_mediator.SplitButtonClicked();
			Assert.IsTrue(barProject.CreateToDoListCalled);
			Assert.AreEqual(newListName, barProject.CreateToDoListLastName);
			Assert.IsTrue(newList.CreateItemCalled);
			Assert.AreEqual(itemContent, newList.CreateItemLastContent);
		}
	}
}
